﻿#ifndef _CONCURRENCY_MEMORY_POOL__H_
#define _CONCURRENCY_MEMORY_POOL__H_

#include "Common.h"
#include "ThreadCache.h"

#ifdef _WIN32
#include <windows.h>
#else
// ...
#endif

template<class T>
class ObjectPool
{
public:
	T* New();
	void Delete(T* ptr);

private:
	// void* _memory; // char*比void*更好，void*不可以进行加减操作
	char* _memory = nullptr; // 内存指针
	size_t _remain_bytes = 0;
	void* _free_list = nullptr; // 回收内存来链表
	static std::mutex _mtx;
};

template<class T>
std::mutex ObjectPool<T>::_mtx;

template<typename T>
T* ObjectPool<T>::New()
{
	// 优先使用_free_list中的回收内存
	T* obj = nullptr;
	if (_free_list)
	{
		void* next = *(static_cast<void**>(_free_list));
		obj = static_cast<T*>(_free_list);
		_free_list = next;
	}
	else
	{
		_mtx.lock();
		// 如果空间用完了呢？
		if (_remain_bytes < sizeof(T))
		{
			// 使用malloc申请空间
			// 在Linux平台下：brk申请内存
			// 在Windows平台下：VirtualAlloc申请内存(malloc的底层)
			_remain_bytes = 128 * 1024;

			// 以8KB的页大小为单位申请内存
			_memory = static_cast<char*>(SystemAlloc(_remain_bytes >> 13));
			if (_memory == nullptr)
			{
				throw std::bad_alloc();
			}
		}
		_mtx.unlock();

		obj = (T*)_memory;
		// 如果申请的内存块不足一个指针的大小
		size_t obj_size = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
		_remain_bytes -= obj_size;
		_memory += obj_size;
	}

	// 定位new进行构造
	new(obj)T;
	return obj;
}

template<typename T>
void ObjectPool<T>::Delete(T* ptr)
{
	// 申请的内存块字节数大于当前平台的指针字节数时
	//*(void**)ptr = _free_list;
	//_free_list = ptr;

	// 如果申请的内存块字节数小于4/8，也可以直接处理
	// 注意：作为delete，自动调用析构函数是必须的
	ptr->~T();

	*(reinterpret_cast<void**>(ptr)) = _free_list;
	_free_list = ptr;
}

#endif